package org.zjx.window.window;

import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import lombok.Setter;
import org.zjx.command.state.StateManager;
import org.zjx.window.action.IAction;
import org.zjx.window.action.StrategyAction;
import org.zjx.window.operation.OperationExecutor;
import org.zjx.window.operation.WindowOperation;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Objects;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 窗口抽象基类
 * 提供窗口管理的基础实现，包括动作队列、状态管理和生命周期控制
 *
 * @author zjx
 * @since 1.0
 */
@Setter
public abstract class AbstractWindow implements IWindow, Runnable {

    /**
     * 窗口名称，用于标识
     */
    private final String name;

    /**
     * 窗口句柄
     */
    protected WinDef.HWND hwnd;

    /**
     * 状态管理器
     */
    private final StateManager stateManager;

    /**
     * 操作执行器
     */
    protected final OperationExecutor executor;

    /**
     * 动作队列，用于异步执行动作
     */
    protected final BlockingQueue<IAction> actionQueue;

    /**
     * 运行状态标志
     */
    private final AtomicBoolean running = new AtomicBoolean(false);

    /**
     * 关闭请求标志
     */
    private final AtomicBoolean shutdownRequested = new AtomicBoolean(false);

    /**
     * 执行线程引用
     */
    private final AtomicReference<Thread> executionThreadRef = new AtomicReference<>();

    /**
     * 终止门闩，用于等待线程终止
     */
    private final CountDownLatch terminationLatch = new CountDownLatch(1);

    /**
     * 动作执行器，用于异步执行动作
     */
    private final ExecutorService actionExecutor;

    /**
     * 屏幕界面截图
     */
    protected BufferedImage screenshot;

    /**
     * 默认构造方法
     *
     * @param hwnd 窗口句柄，不能为null
     * @param executor 操作执行器，不能为null
     * @throws IllegalArgumentException 如果 hwnd或executor为 null
     */
    public AbstractWindow(WinDef.HWND hwnd, OperationExecutor executor) {
        this(hwnd, executor, 50); // 默认队列大小50
    }

    /**
     * 完整构造方法
     *
     * @param hwnd 窗口句柄，不能为null
     * @param executor 操作执行器，不能为null
     * @param queueCapacity 动作队列容量
     * @throws IllegalArgumentException 如果hwnd或executor为null，或queueCapacity小于1
     */
    public AbstractWindow(WinDef.HWND hwnd, OperationExecutor executor, int queueCapacity) {
        this.hwnd = Objects.requireNonNull(hwnd, "窗口句柄不能为 null");
        this.executor = Objects.requireNonNull(executor, "操作执行器不能为 null");

        if (queueCapacity < 1) {
            throw new IllegalArgumentException("队列容量必须大于0: " + queueCapacity);
        }

        this.name = "window-" + System.currentTimeMillis();
        this.stateManager = new StateManager();
        this.actionQueue = new LinkedBlockingQueue<>(queueCapacity);
        this.actionExecutor = createActionExecutor();

        // 设置执行器的窗口关联
        this.executor.setWindow(this);

        start();
    }

    /**
     * 创建动作执行器
     *
     * @return 配置好的执行器服务
     */
    protected ExecutorService createActionExecutor() {
        return Executors.newSingleThreadExecutor(r -> {
            Thread t = new Thread(r, "window-action-executor-" + getName());
            t.setDaemon(true);
            return t;
        });
    }

    @Override
    public WinDef.HWND getHwnd() {
        return hwnd;
    }

    @Override
    public String getTitle() {
        char[] buffer = new char[1024];
        int length = User32.INSTANCE.GetWindowText(hwnd, buffer, buffer.length);
        return length > 0 ? new String(buffer, 0, length) : "Unknown";
    }

    @Override
    public boolean isExists() {
        return User32.INSTANCE.IsWindow(hwnd);
    }

    @Override
    public Rectangle getBounds() {
        WinDef.RECT rect = new WinDef.RECT();
        User32.INSTANCE.GetWindowRect(hwnd, rect);
        return new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
    }

    @Override
    public Rectangle getTrueBounds() {
        // 默认实现与getBounds相同，子类可重写
        return getBounds();
    }

    @Override
    public void activate() {
        if (isExists()) {
            User32.INSTANCE.SetForegroundWindow(hwnd);
        }
    }

    @Override
    public boolean isActive() {
        return ActivationManager.getActivationWindow().getHwnd() == hwnd;
    }

    @Override
    public boolean waitForActive(long timeoutMs) {
        if (timeoutMs < 0) {
            throw new IllegalArgumentException("超时时间不能为负数: " + timeoutMs);
        }

        long endTime = System.currentTimeMillis() + timeoutMs;
        while (System.currentTimeMillis() < endTime) {
            if (isActive()) {
                return true;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            }
        }
        return false;
    }

    @Override
    public void close() {
        if (hwnd == null || !isExists()) {
            return;
        }

        try {
            shutdown();

            // 发送关闭消息
            User32.INSTANCE.SendMessage(hwnd, 0x0010, null, null);

            // 等待窗口关闭
            long endTime = System.currentTimeMillis() + 3000;
            while (System.currentTimeMillis() < endTime) {
                if (!User32.INSTANCE.IsWindow(hwnd)) {
                    return;
                }
                TimeUnit.MILLISECONDS.sleep(100);
            }

            // 强制关闭超时的窗口
            User32.INSTANCE.PostMessage(hwnd, 0x0010, null, null);
        } catch (Exception e) {
            System.err.println("关闭窗口失败: " + e.getMessage());
        }
    }

    @Override
    public StateManager getState() {
        return stateManager;
    }

    @Override
    public void updateState() {
        // 默认空实现，子类可重写以更新特定状态
    }

    @Override
    public BufferedImage getScreenshot() {
        if (screenshot == null) flushScreenshot();
        return screenshot;
    }

    @Override
    public void flushScreenshot() {
        screenshot = executor.screenshot();
    }

    @Override
    public void start() {
        if (running.compareAndSet(false, true)) {
            Thread thread = new Thread(this, "window-thread-" + getName());
            thread.setDaemon(true);
            thread.setUncaughtExceptionHandler((t, e) -> {
                System.err.println("窗口线程异常: " + e.getMessage());
                running.set(false);
            });
            thread.start();
        }
    }

    @Override
    public void shutdown() {
        if (shutdownRequested.compareAndSet(false, true)) {
            running.set(false);

            // 中断执行线程
            Thread executionThread = executionThreadRef.get();
            if (executionThread != null && executionThread.isAlive()) {
                executionThread.interrupt();
            }

            // 清空队列
            actionQueue.clear();

            // 关闭执行器
            shutdownActionExecutor();
        }
    }

    /**
     * 关闭动作执行器
     */
    protected void shutdownActionExecutor() {
        actionExecutor.shutdown();
        try {
            if (!actionExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
                actionExecutor.shutdownNow();
            }
        } catch (InterruptedException e) {
            actionExecutor.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }

    @Override
    public boolean isRunning() {
        return running.get();
    }

    @Override
    public void execute(WindowOperation operation) {
        Objects.requireNonNull(operation, "窗口操作不能为null");
        operation.execute(executor);
    }

    @Override
    public OperationExecutor getExecutor() {
        return executor;
    }

    @Override
    public void run() {
        executionThreadRef.set(Thread.currentThread());

        try {
            while (running.get() && !Thread.currentThread().isInterrupted()) {
                try {
                    if (!isValid()) {
                        System.err.println("窗口无效，停止处理: " + getName());
                        break;
                    }

                    // 从队列获取动作，最多等待100ms
                    IAction action = actionQueue.poll(100, TimeUnit.MILLISECONDS);
                    if (action != null) {
                        executeAction(action);
                    } else {
                        // 无动作时执行策略动作
                        submitStrategyAction();
                    }

                } catch (InterruptedException e) {
                    if (shutdownRequested.get()) {
                        break;
                    }
                    Thread.currentThread().interrupt();
                    break;
                } catch (Exception e) {
                    System.err.println("窗口处理异常: " + e.getMessage());
                    // 继续运行，不因异常退出
                }
            }
        } finally {
            running.set(false);
            terminationLatch.countDown();
            System.out.println("窗口线程终止: " + getName());
        }
    }

    /**
     * 提交策略动作（当队列为空时执行）
     */
    protected void submitStrategyAction() {
        try {
            // 检查命令队列是否为空
            if (actionQueue.isEmpty()) {
                // 队列为空，提交策略命令

                StrategyAction strategyAction = new StrategyAction(this);
                submitAction(strategyAction);
            }
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }


    @Override
    public CompletableFuture<Boolean> submitAction(IAction action) {
        Objects.requireNonNull(action, "动作不能为null");

        if (!running.get() || shutdownRequested.get()) {
            return CompletableFuture.completedFuture(false);
        }

        if (!isValid()) {
            return CompletableFuture.completedFuture(false);
        }

        // 尝试添加到队列
        boolean offered = actionQueue.offer(action);
        if (!offered) {
            System.err.println("动作队列已满，无法提交: " + action.getActionName());
            return CompletableFuture.completedFuture(false);
        }

        // 返回异步结果
        return CompletableFuture.supplyAsync(() -> {
            // 注意：这里只是跟踪提交状态，实际执行在主循环中
            return true;
        }, actionExecutor).exceptionally(throwable -> {
            System.err.println("提交动作异常: " + throwable.getMessage());
            return false;
        });
    }

    @Override
    public void executeAction(IAction action) {
        Objects.requireNonNull(action, "动作不能为null");

        String actionName = action.getActionName();
        long startTime = System.currentTimeMillis();
        boolean success = false;

        try {
            System.out.println("开始执行动作: " + actionName);
            success = action.execute();
            long duration = System.currentTimeMillis() - startTime;

            if (success) {
                System.out.println("动作执行成功: " + actionName + " [耗时: " + duration + "ms]");
            } else {
                System.err.println("动作执行失败: " + actionName + " [耗时: " + duration + "ms]");
            }

        } catch (InterruptedException e) {
            System.err.println("动作执行被中断: " + actionName);
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            System.err.println("动作执行异常: " + actionName + " - " + e.getMessage());
            long duration = System.currentTimeMillis() - startTime;
            System.err.println("异常动作耗时: " + duration + "ms");
        }
    }

    @Override
    public boolean isValid() {
        return isExists() && running.get() && !shutdownRequested.get();
    }

    @Override
    public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
        Objects.requireNonNull(unit, "时间单位不能为null");

        boolean threadTerminated = terminationLatch.await(timeout, unit);
        boolean executorTerminated = actionExecutor.awaitTermination(timeout, unit);

        return threadTerminated && executorTerminated;
    }

    @Override
    public String getName() {
        return name;
    }

    /**
     * 获取动作队列大小
     *
     * @return 当前队列中的动作数量
     */
    public int getQueueSize() {
        return actionQueue.size();
    }

    /**
     * 获取队列剩余容量
     *
     * @return 队列剩余容量
     */
    public int getRemainingQueueCapacity() {
        return actionQueue.remainingCapacity();
    }

    /**
     * 清空动作队列
     */
    public void clearActionQueue() {
        actionQueue.clear();
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            if (running.get()) {
                System.err.println("窗口未正确关闭，强制关闭: " + getName());
                shutdown();
            }
        } finally {
            super.finalize();
        }
    }
}